home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / xinetd / xinetd.2.0.6 / builtins.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-22  |  7.2 KB  |  346 lines

  1. /*
  2.  * (c) Copyright 1992 by Panagiotis Tsirigotis
  3.  * All rights reserved.  The file named COPYRIGHT specifies the terms 
  4.  * and conditions for redistribution.
  5.  */
  6.  
  7. static char RCSid[] = "$Id: builtins.c,v 5.1 1992/11/01 00:01:21 panos Exp $" ;
  8.  
  9. #include <sys/types.h>
  10. #include <sys/socket.h>
  11. #include <errno.h>
  12. #include <time.h>
  13. #include <syslog.h>
  14.  
  15. #include "str.h"
  16.  
  17. #include "config.h"
  18. #include "builtin.h"
  19. #include "defs.h"
  20. #include "server.h"
  21.  
  22. extern int errno ;
  23.  
  24. time_t time() ;
  25.  
  26. void msg() ;
  27.  
  28. void stream_echo() ;
  29. void dgram_echo() ;
  30. void stream_discard() ;
  31. void dgram_discard() ;
  32. void stream_time() ;
  33. void dgram_time() ;
  34. void stream_daytime() ;
  35. void dgram_daytime() ;
  36. void stream_chargen() ;
  37. void dgram_chargen() ;
  38.  
  39.  
  40. static struct builtin_service builtin_services[] =
  41.     {
  42.         { "echo",            SOCK_STREAM,        stream_echo,             FORK      },
  43.         { "echo",            SOCK_DGRAM,            dgram_echo,                NO_FORK    },
  44.         { "discard",        SOCK_STREAM,        stream_discard,        FORK        },
  45.         { "discard",        SOCK_DGRAM,            dgram_discard,            NO_FORK    },
  46.         { "time",            SOCK_STREAM,        stream_time,            NO_FORK    },
  47.         { "time",            SOCK_DGRAM,            dgram_time,                NO_FORK    },
  48.         { "daytime",        SOCK_STREAM,        stream_daytime,        NO_FORK    },
  49.         { "daytime",        SOCK_DGRAM,            dgram_daytime,            NO_FORK    },
  50.         { "chargen",        SOCK_STREAM,        stream_chargen,        FORK        },
  51.         { "chargen",        SOCK_DGRAM,            dgram_chargen,            NO_FORK    },
  52.         { NULL,                0,                        NULL,                        NO_FORK  }
  53.     } ;
  54.  
  55. struct builtin_service *find_builtin( service_name, type )
  56.     char *service_name ;
  57.     int type ;
  58. {
  59.     register struct builtin_service *bsp ;
  60.     char *func = "find_builtin" ;
  61.  
  62.     if ( bsp = builtin_lookup( builtin_services, service_name, type ) )
  63.         return( bsp ) ;
  64.     
  65.     msg( LOG_ERR, func, "No such internal service", service_name ) ;
  66.     return( NULL ) ;
  67. }
  68.  
  69.  
  70. struct builtin_service *builtin_lookup( services, service_name, type )
  71.     struct builtin_service services[] ;
  72.     char *service_name ;
  73.     int type ;
  74. {
  75.     register struct builtin_service *bsp ;
  76.  
  77.     for ( bsp = &services[0] ; bsp->name != NULL ; bsp++ )
  78.         if ( EQ( bsp->name, service_name ) && bsp->socket_type == type )
  79.             return( bsp ) ;
  80.     return( NULL ) ;
  81. }
  82.  
  83.  
  84.  
  85. PRIVATE void stream_echo( serp )
  86.     struct server *serp ;
  87. {
  88.     char buf[ DATAGRAM_SIZE ] ;
  89.     register int cc ;
  90.     int descriptor = SERVER_FD( serp ) ;
  91.     status_e write_buf() ;
  92.  
  93.     for ( ;; )
  94.     {
  95.         cc = read( descriptor, buf, sizeof( buf ) ) ;
  96.         if ( cc == 0 )
  97.             break ;
  98.         if ( cc == -1 )
  99.             if ( errno == EINTR )
  100.                 continue ;
  101.             else
  102.                 break ;
  103.  
  104.         if ( write_buf( descriptor, buf, cc ) == FAILED )
  105.             break ;
  106.     }
  107. }
  108.  
  109.  
  110. PRIVATE void dgram_echo( serp )
  111.     struct server *serp ;
  112. {
  113.     char buf[ DATAGRAM_SIZE ] ;
  114.     struct sockaddr_in sin ;
  115.     int sin_len ;
  116.     int cc ;
  117.     int descriptor = SERVER_FD( serp ) ;
  118.  
  119.     cc = recvfrom( descriptor, buf, sizeof( buf ), 0, SA( &sin ), &sin_len ) ;
  120.     if ( cc != -1 )
  121.         (void) sendto( descriptor, buf, cc, 0, SA( &sin ), sizeof( sin ) ) ;
  122. }
  123.  
  124.  
  125. PRIVATE void stream_discard( serp )
  126.     struct server *serp ;
  127. {
  128.     char buf[ DATAGRAM_SIZE ] ;
  129.     register int cc ;
  130.  
  131.     for ( ;; )
  132.     {
  133.         cc = read( SERVER_FD( serp ), buf, sizeof( buf ) ) ;
  134.         if ( cc == 0 || cc == -1 && errno != EINTR )
  135.             break ;
  136.     }
  137. }
  138.  
  139.  
  140. PRIVATE void dgram_discard( serp )
  141.     struct server *serp ;
  142. {
  143.     char buf[ DATAGRAM_SIZE ] ;
  144.  
  145.     (void) recv( SERVER_FD( serp ), buf, sizeof( buf ), 0 ) ;
  146. }
  147.  
  148.  
  149.  
  150. /*
  151.  * Generate the current time using the SMTP format:
  152.  *        02 FEB 1991 12:31:42 MST
  153.  *
  154.  * The result is placed in buf.
  155.  * buflen is a value-result parameter. It indicates the size of
  156.  * buf and on exit it has the length of the string placed in buf.
  157.  */
  158. PRIVATE void daytime_protocol( buf, buflen )
  159.     char *buf ;
  160.     int *buflen ;
  161. {
  162.     static char *month_name[] =
  163.         {
  164.             "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
  165.             "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"
  166.         } ;
  167.     time_t now ;
  168.     struct tm *tmp ;
  169.     int size = *buflen ;
  170.     
  171.     (void) time( &now ) ;
  172.     tmp = localtime( &now ) ;
  173.     strx_print( buflen, buf, size,
  174.         "%02d %s %d %02d:%02d:%02d %s\r\n",
  175.             tmp->tm_mday, month_name[ tmp->tm_mon ], 1900 + tmp->tm_year,
  176.                 tmp->tm_hour, tmp->tm_min, tmp->tm_sec, tmp->tm_zone ) ;
  177. }
  178.  
  179.  
  180. PRIVATE void stream_daytime( serp )
  181.     struct server *serp ;
  182. {
  183.     char time_buf[ DATAGRAM_SIZE ] ;
  184.     int buflen = sizeof( time_buf ) ;
  185.  
  186.     daytime_protocol( time_buf, &buflen ) ;
  187.     (void) write_buf( SERVER_FD( serp ), time_buf, buflen ) ;
  188. }
  189.  
  190.  
  191. PRIVATE void dgram_daytime( serp )
  192.     struct server *serp ;
  193. {
  194.     char time_buf[ DATAGRAM_SIZE ] ;
  195.     int buflen = sizeof( time_buf ) ;
  196.     struct sockaddr_in sin ;
  197.     int sin_len = sizeof( sin ) ;
  198.     int descriptor = SERVER_FD( serp ) ;
  199.  
  200.     if ( recvfrom( descriptor, time_buf, sizeof( time_buf ), 0,
  201.                 SA( &sin ), &sin_len ) == -1 )
  202.         return ;
  203.  
  204.     daytime_protocol( time_buf, &buflen ) ;
  205.     
  206.     (void) sendto( descriptor, time_buf, buflen, 0, SA(&sin), sizeof( sin ) ) ;
  207. }
  208.  
  209.  
  210. #define TIME_OFFSET            2208988800
  211.  
  212. PRIVATE void time_protocol( timep )
  213.     register u_long *timep ;
  214. {
  215.     time_t now ;
  216.  
  217.     (void) time( &now ) ;
  218.     *timep = now + TIME_OFFSET ;
  219.     *timep = htonl( *timep ) ;
  220. }
  221.  
  222.  
  223. PRIVATE void stream_time( serp )
  224.     struct server *serp ;
  225. {
  226.     u_long now ;
  227.  
  228.     time_protocol( &now ) ;
  229.     (void) write_buf( SERVER_FD( serp ), (char *) &now, sizeof( now ) ) ;
  230. }
  231.  
  232.  
  233. PRIVATE void dgram_time( serp )
  234.     struct server *serp ;
  235. {
  236.     char buf[ DATAGRAM_SIZE ] ;
  237.     struct sockaddr_in sin ;
  238.     int sin_len = sizeof( sin ) ;
  239.     int fd = SERVER_FD( serp ) ;
  240.     u_long now ;
  241.  
  242.     if ( recvfrom( fd, buf, sizeof( buf ), 0, SA( &sin ), &sin_len ) == -1 )
  243.         return ;
  244.  
  245.     time_protocol( &now ) ;
  246.     (void) sendto( fd, (char *) &now, sizeof( now ), 0, SA( &sin ), sin_len ) ;
  247. }
  248.  
  249.  
  250. #define ASCII_PRINTABLE_CHARS                94
  251. #define LINE_LENGTH                            72
  252.  
  253. #define RING_BUF_SIZE                        ASCII_PRINTABLE_CHARS + LINE_LENGTH
  254.  
  255. static char ring_buf[ RING_BUF_SIZE ] ;
  256. static char *ring ;
  257.  
  258.  
  259. #define ASCII_START                ( ' ' + 1 )
  260. #define ASCII_END                    126
  261.  
  262. #define min( a, b )                ((a)<(b) ? (a) : (b))
  263.  
  264. PRIVATE char *generate_line( buf, len )
  265.     char *buf ;
  266.     int len ;
  267. {
  268.     int line_len = min( LINE_LENGTH, len-2 ) ;
  269.  
  270.     if ( line_len < 0 )
  271.         return( NULL ) ;
  272.  
  273.     if ( ring == NULL )
  274.     {
  275.         register char ch ;
  276.         register char *p ;
  277.  
  278.         for ( p = ring_buf, ch = ASCII_START ;
  279.                             p < &ring_buf[ RING_BUF_SIZE ] ; p++ )
  280.         {
  281.             *p = ch++ ;
  282.             if ( ch == ASCII_END )
  283.                 ch = ASCII_START ;
  284.         }
  285.         ring = ring_buf ;
  286.     }
  287.     bcopy( ring, buf, line_len ) ;
  288.     buf[ line_len   ] = '\r' ;
  289.     buf[ line_len+1 ] = '\n' ;
  290.  
  291.     ring++ ;
  292.     if ( &ring_buf[ RING_BUF_SIZE ] - ring < LINE_LENGTH )
  293.         ring = ring_buf ;
  294.     return( buf ) ;
  295. }
  296.  
  297.  
  298. PRIVATE void stream_chargen( serp )
  299.     struct server *serp ;
  300. {
  301.     char line_buf[ LINE_LENGTH+2 ] ;
  302.     int descriptor = SERVER_FD( serp ) ;
  303.     status_e write_buf() ;
  304.  
  305.     (void) shutdown( descriptor, 0 ) ;
  306.     for ( ;; )
  307.     {
  308.         if ( generate_line( line_buf, sizeof( line_buf ) ) == NULL )
  309.             break ;
  310.         if ( write_buf( descriptor, line_buf, sizeof( line_buf ) ) == FAILED )
  311.             break ;
  312.     }
  313. }
  314.  
  315.  
  316. #define RESPONSE_SIZE                512
  317.  
  318.  
  319. PRIVATE void dgram_chargen( serp )
  320.     struct server *serp ;
  321. {
  322.     char buf[ DATAGRAM_SIZE ] ;
  323.     register char *p ;
  324.     struct sockaddr_in sin ;
  325.     int sin_len = sizeof( sin ) ;
  326.     int fd = SERVER_FD( serp ) ;
  327.     register int len ;
  328.     register int left = sizeof( buf ) ;
  329.  
  330.     if ( recvfrom( fd, buf, sizeof( buf ), 0, SA( &sin ), &sin_len ) == -1 )
  331.         return ;
  332.  
  333. #if DATAGRAM_SIZE < LINE_LENGTH+2
  334.     bad_variable = 1 ;        /* this will cause a compilation error */
  335. #endif
  336.  
  337.     for ( p = buf ; left > 2 ; left -= len, p += len )
  338.     {
  339.         len = min( LINE_LENGTH+2, left ) ;
  340.         if ( generate_line( p, len ) == NULL )
  341.             break ;
  342.     }
  343.     (void) sendto( fd, buf, p-buf, 0, SA( &sin ), sin_len ) ;
  344. }
  345.  
  346.